// JavaScript Document
/* 
 Cíl:
 jednoznačná identifikace podpisu -> převod do znakového/číselného řetězce
 vyhledatelného/porovnatelného s uloženým vzorem/předpisem.
 
 Měřitelné atributy:
 1-  Velikost   (relativní)
 2-  Obsah (úroveň zaplnění plochy - řídké/husté podpisy)
 3-  Sklon    - průměrný
 4-  Monotónnost
 5-  Spojitost   / fragmentace
 6-  Poměr výška / šířka
 7-  Poměr fragmentů
 8-  Šikmost/Špičatost (2. a 3. moment)
 9-  Dynamika v čase    a rychlost
 10-  Smyčky vs. Linearity
 11-  Úhly
 12-  Umístění
 
 
 Metoda:
 
 The mathematical basis for the Random Decrement Technique of vibration signature analysis is established. 
 The general relationship between the autocorrelation function of a random process and the
 Randomdec signature is derived. For the particular case of a linear time invariant 
 system excited by a zero-mean, stationary, Gaussian random process,
 a Randomdec signature of the output is shown to be proportional to the auto-correlation of the output. 
 Example Randomdec signatures are computed from acceleration response
 time histories from an offshore platform.
 */

//CALCULATE stat data
$('#calculate').mousedown(function(e)
{
    var denst = density(clickX, clickY);
    var segmentNr = primitiveFragments(clickX, clickY, clickDrag).segmentNr;

    $('#showData').mousedown();
});

$('#doStats').mousedown(function(e)
{
    var clickDeltaTime = [];
    var startTime = clickTime[0];
    for (index = 0; index < clickX.length; index++) {
        clickDeltaTime.push(clickTime[index] - startTime);
    }
    
    var denst = density(clickX, clickY);
    var segments = primitiveFragments(clickX, clickY, clickDrag);
    var w = document.getElementById('canvas').width;
    var h = document.getElementById('canvas').height;
    var size = sizeOfSig(clickX, clickY, w, h);
    var skew = skewOfSig(clickX, clickY, segments.segmentNr);
    var lrXt = linRegresion(clickDeltaTime, clickX);
    var lrYt = linRegresion(clickDeltaTime, clickY);
    var lrXY = linRegresion(clickX, clickY);
    $('#showData').mousedown();

    var htmlStats = 'Density: ' + denst + '<BR>';
    htmlStats += 'Segments Count:  ' + segments.segment + '<BR>';
    htmlStats += 'Relative Width:  ' + size.w + '<BR>';
    htmlStats += 'Relative Height: ' + size.h + '<BR>';
    htmlStats += 'Vertical Stretch: ' + size.s + '<BR>';

    htmlStats += 'Array skewness: ' + skew.arraySkew + '<BR>';
    htmlStats += 'Average skewness: ' + skew.avgSkew + '<BR>';
    htmlStats += 'Weighted Avg. skewness: ' + skew.weiSkew + '<BR>';
    //roundnes missing = 1 - (skewed.lenght / fullSegment.lenght);

//shifted -- transponed y and x should be used instead (1st point = [0,0]
    htmlStats += 'Linear Regression X.time ' + lrXt.B + 'x + ' + lrXt.A + '<BR>';
    htmlStats += 'Linear Regression Y.time ' + lrYt.B + 'x + ' + lrYt.A + '<BR>';
    htmlStats += 'Linear Regression X.Y ' + lrXY.B + 'x + ' + lrXY.A + '<BR>';
    
 //lin reg. of segments now:
    
    //Bayesian filter should follow:





    var capturedData = document.getElementById('StatResults');
    capturedData.innerHTML = htmlStats;
});


function sizeOfSig(coordX, coordY, canvasW, canvasH) {

    var maxX = coordX[0];
    var minX = coordX[0];
    var maxY = coordY[0];
    var minY = coordY[0];

    for (index = 0; index < (coordX.length); index++) {

        if (coordX[index] >= maxX) {
            maxX = coordX[index];
        }
        if (coordX[index] <= minX) {
            minX = coordX[index];
        }
        if (coordY[index] >= maxY) {
            maxY = coordY[index];
        }
        if (coordY[index] <= minY) {
            minY = coordY[index];
        }
    }

    return  {w: (maxX - minX) / canvasW,
        h: (maxY - minY) / canvasH,
        s: (maxY - minY) / (maxX - minX)
    };

}
;

function density(coordX, coordY) {

    var maxX = coordX[0];
    var minX = coordX[0];
    var maxY = coordY[0];
    var minY = coordY[0];

    for (index = 0; index < (coordX.length); index++) {

        if (coordX[index] >= maxX) {
            maxX = coordX[index];
        }
        if (coordX[index] <= minX) {
            minX = coordX[index];
        }
        if (coordY[index] >= maxY) {
            maxY = coordY[index];
        }
        if (coordY[index] <= minY) {
            minY = coordY[index];
        }
    }
    minX--;
    minY--;
    return (coordX.length / ((maxX - minX) * (maxY - minY))) * 100;
}
;

function skewOfSig(coordX, coordY, segments) {


    var BegPointIndex;
    var EndPointIndex;

    var BegPointX;
    var BegPointY;
    var EndPointX;
    var EndPointY;

    var GotBegPoint = false;
    var GotEndPoint = false;

    var LeftPointX;
    var LeftPointY;
    var RightPointX;
    var RightPointY;


    var skews = [];
    var lengthX, lengthY, lengthXY;

    var totalSkew = 0, averageSkew = 0, weightedSkew = 0;

    for (index = 0; index < (coordX.length); index++) {
        if (index === 0 || (segments[index - 1] !== segments[index])) {
            BegPointX = coordX[index];
            BegPointY = coordY[index];
            BegPointIndex = index;
            GotBegPoint = true;
        }

        if (index === coordX.length - 1 || (segments[index] !== segments[index + 1])) {
            EndPointX = coordX[index];
            EndPointY = coordY[index];
            EndPointIndex = index;
            GotEndPoint = true;
        }

        if (GotBegPoint === false || GotEndPoint === false) {
            continue; //never go on, until got both begin and end points of segment...
        }
        GotBegPoint = false;
        GotEndPoint = false;


        if (BegPointX <= EndPointX) {
            LeftPointX = BegPointX;
            LeftPointY = BegPointY;
            RightPointX = EndPointX;
            RightPointY = EndPointY;
        }
        else {
            LeftPointX = EndPointX;
            LeftPointY = EndPointY;
            RightPointX = BegPointX;
            RightPointY = BegPointY;
        }

        lengthX = RightPointX - LeftPointX;
        lengthY = (RightPointY - LeftPointY) * -1; //tranform XY up to down 
        lengthXY = Math.abs(lengthX) + Math.abs(lengthY);

        if (lengthXY !== 0) {
            skews.push(lengthY / lengthXY);
            totalSkew += (lengthY / lengthXY);
            weightedSkew += (lengthY / lengthXY) * (EndPointIndex - BegPointIndex);
        }
        else {
            skews.push(1);
            totalSkew += (1);
            weightedSkew += (1) * (EndPointIndex - BegPointIndex);
        }


    }

    for (index = 0; index < (skews.length); index++) {

    }

    averageSkew = totalSkew / (skews.length);
    weightedSkew = weightedSkew / (coordX.length);

    return  {arraySkew: skews,
        avgSkew: averageSkew,
        weiSkew: weightedSkew
    };

}
;


function primitiveFragments(coordX, coordY, clickDrag) {

    var segment = 0;
    segmentNr = new Array();

    var goUpX;
    var goDownX;
    var goUpY;
    var goDownY;

//najdi fragmenty:
    for (index = 0; index < coordX.length; index++) {

        if (clickDrag[index] !== true) {
            segment++;
            goUpX = false;
            goDownX = false;
            goUpY = false;
            goDownY = false;
        }
        else {
            if (clickX[index] > clickX[index - 1]) {
                goUpX = true;
            }
            if (clickX[index] < clickX[index - 1]) {
                goDownX = true;
            }
            if (clickY[index] > clickY[index - 1]) {
                goUpY = true;
            }
            if (clickY[index] < clickY[index - 1]) {
                goDownY = true;
            }

            if ((goDownY === true && goUpY === true) || (goDownX === true && goUpX === true)) {
                segment++;
                goUpY = false;
                goDownY = false;
                goUpX = false;
                goDownX = false;
            }
        }

        segmentNr.push(segment);

    }
    return  {segmentNr: segmentNr,
        segment: segment};

}
;

function linRegresion(X, Y) {

//check X.lenght === Y.lenght;
//check X.lenght > 0;

    var A = 0, B = 0; //y=slope*X + intercept
    var x, y;

    var sum_x = 0;
    var sum_y = 0;
    var sum_xx = 0;
    var sum_xy = 0;
    var data_length = 0;

    for (index = 0; index < (X.length); index++) {
        x = X[index];
        y = Y[index];

        sum_x += x;
        sum_y += y;
        sum_xx += x * x;
        sum_xy += x * y;

    }
    data_length = X.length;


    B = ((data_length * sum_xy) - (sum_x * sum_y)) /
            ((data_length * sum_xx) - (sum_x * sum_x));

    A = (sum_y / data_length) - ((B * sum_x) / data_length);


//doplnit R2 - koeficient determinace...

    return {B: B,
        A: A};
}
;

function extremal() {
    var GoAsc = false;      //ascending move
    var GoDesc = false;      //descending move
    var myInputArray = [];
    var myExtremalsArray = [];
    var firstDiff;

    for (index = 0; index < (myArray.length - 1); index++) {
        //myArray.length - 1 is because not to exceed array boundary, 
        //last array element does not have any follower to test it

        firstDiff = (myArray[index] - myArray[index + 1]);

        if (firstDiff > 0) {
            GoAsc = true;
        }
        if (firstDiff < 0) {
            GoDesc = true;
        }

        if (GoAsc === true && GoDesc === true) {
            myExtremalsArray.push(myArray[index]);
            GoAsc = false;
            GoDesc = false;
            //if firstDiff > 0 ---> max
            //if firstDiff < 0 ---> min
        }

    }
}
